package vesion2.tool;


import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader;

import javax.sound.sampled.*;
import java.io.*;
import java.net.URL;
import java.net.URLDecoder;

public class PlayMp3{
    AudioInputStream stream;
    SourceDataLine  sdLine;
    volatile boolean isRun;
    Thread playThread;
    boolean hasRelease;
    volatile   boolean isOver;
    File file;
    boolean isStart=false;
    public PlayMp3(String filePath){
        try {
            file=new File(filePath);
            initStream();
        } catch(Exception e){
            e.printStackTrace();
            stream=null;
            sdLine=null;
        }
        isRun=true;
        hasRelease=false;
        isOver=false;
    }

    public PlayMp3(URL url){
        try {
            String cp=URLDecoder.decode(url.getPath(),"utf-8");
            String fp=cp.replace("/","\\");
            file=new File(fp);
            initStream();
        } catch(Exception e){
            e.printStackTrace();
            stream=null;
            sdLine=null;
        }
        isRun=true;
        hasRelease=false;
        isOver=false;
    }
    @Override
    protected void finalize() throws Throwable{
        release();
        System.out.println("结束啦");
    }

    private void initStream() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        if (!file.exists() || !file.getPath().toLowerCase().endsWith(".mp3")) {
            throw new RuntimeException("文件不存在");
        }
        stream=new MpegAudioFileReader().getAudioInputStream(file);
        //设定输出格式为pcm格式的音频文件
        AudioFormat baseFormat = stream.getFormat();
        AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16,
                baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);
        stream = AudioSystem.getAudioInputStream(format, stream);
        AudioFormat target = stream.getFormat();
        DataLine.Info dInfo = new DataLine.Info(SourceDataLine.class, target, AudioSystem.NOT_SPECIFIED);
        sdLine=(SourceDataLine) AudioSystem.getLine(dInfo);
        sdLine.open(target);
        sdLine.start();
    }

    private void reInit() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        release();
        stream=new MpegAudioFileReader().getAudioInputStream(file);
        //设定输出格式为pcm格式的音频文件
        AudioFormat baseFormat = stream.getFormat();
        AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16,
                baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);
        stream = AudioSystem.getAudioInputStream(format, stream);
        AudioFormat target = stream.getFormat();
        DataLine.Info dInfo = new DataLine.Info(SourceDataLine.class, target, AudioSystem.NOT_SPECIFIED);
        sdLine=(SourceDataLine) AudioSystem.getLine(dInfo);
        sdLine.open(target);
        sdLine.start();
    }

    private void play(boolean isLoop) throws IOException, InterruptedException, UnsupportedAudioFileException, LineUnavailableException {
        if(stream==null)
            return;
        int len=-1;
        isStart=true;
        byte[] buffer = new byte[1024];
//        Clip clip = AudioSystem.getClip();
//        clip.open(stream);
        do {
            while ((len = stream.read(buffer)) > 0 && !isOver) {
                if (!isRun)
                    synchronized (this) {
                        wait();
                    }
                sdLine.write(buffer, 0, len);
            }
            reInit();
        } while (isLoop && !isOver);
        System.out.println("over");
        isRun=false;
        release();
    }

    public void startPlay(boolean isCycle){
        if(playThread==null||!playThread.isAlive())
          playThread =new Thread(()->{
              try {
                  play(isCycle);
              } catch (IOException e) {
                  e.printStackTrace();
              } catch (InterruptedException e) {
                  e.printStackTrace();
              } catch (UnsupportedAudioFileException e) {
                  e.printStackTrace();
              } catch (LineUnavailableException e) {
                  e.printStackTrace();
              }
          });
        playThread.start();
    }

    public void stopPlay(){
            isRun = false;
    }

    public boolean isPlaying(){
        return isRun;
    }

    public void close(){
        isOver=true;
    }

    public void keep(){
        synchronized (this) {
            isRun = true;
            notify();
        }
    }

    public void release(){
        if(sdLine==null)
            return;
        sdLine.drain();
        sdLine.stop();
        sdLine.close();
        hasRelease=true;
    }

    public boolean isStart(){
        return isStart;
    }

}
